#ifndef HIGEOMINL_HPP
#define HIGEOMINL_HPP

#include <cv.h>

/*
 *  HIGeom-inl.hpp
 *  
 *
 *  Created by Rasmus Kyng on 30/01/2011.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */

namespace hi {
	inline void forceInside( const cv::Size& outerFrame, cv::Rect& innerRect ) {
		//forcing inner rect to stay inside outer rect  --- assuming inner rect fits inside the outer rect!
		if ( innerRect.x < 0 ) innerRect.x = 0;
		if ( outerFrame.width < innerRect.x + innerRect.width ) innerRect.x = outerFrame.width - innerRect.width;
		if ( innerRect.y < 0 ) innerRect.y = 0;
		if ( outerFrame.height < innerRect.y + innerRect.height ) innerRect.y = outerFrame.height - innerRect.height;
	}

	inline bool intervalsIntersect( int interval_a_start, int interval_a_len, int interval_b_start, int interval_b_len ) { //sometimes camelCase just isn't nice
		if ( interval_a_start <= interval_b_start ) {
			if ( interval_b_start < interval_a_start+interval_a_len) {
				return true;
			} else {
				return false;
			}
		} else {
			if ( interval_a_start < interval_b_start+interval_b_len) {
				return true;
			} else {
				return false;
			}
		}
	}
	
	inline bool rectanglesIntersect( const cv::Rect& rectA, const cv::Rect& rectB ) {
		//returns true if the rectangles intersect
		return intervalsIntersect( rectA.x, rectA.width, rectB.x, rectB.width ) && intervalsIntersect( rectA.y, rectA.height, rectB.y, rectB.height );
	}
	
	//This returns the rectangle defined by the overlap between the first and second rect, given in the frame of reference defined by the first rect.
	//If the intersection is empty, Rect(0,0,-1,-1) is returned.
	inline cv::Rect rectOfSecondInFirst( const cv::Rect& firstRect, const cv::Rect& secondRect ) {
		cv::Rect resultRect;
		// -- computing x-axis intersection -- //
		//intersection origin
		if ( firstRect.x <= secondRect.x ) {
			if ( secondRect.x < firstRect.x+firstRect.width) {
				resultRect.x = secondRect.x - firstRect.x;
				//intersection width
				if (resultRect.x + secondRect.width < firstRect.width) {
					resultRect.width = secondRect.width;
				} else {
					resultRect.width = firstRect.width - resultRect.x;
				}
			} else {
				return cv::Rect(0,0,-1,-1);
			}
		} else {
			if ( firstRect.x < secondRect.x+secondRect.width) {
				resultRect.x = 0; //crop interval start point inside firstRect 
				resultRect.width = secondRect.width - ( firstRect.x - secondRect.x ); //crop interval width to match cropped startpoint
				//crop intersection width further to fit inside first rect
				if (firstRect.width < resultRect.x + resultRect.width) {
					resultRect.width = firstRect.width - resultRect.x;
				}  
			} else {
				return cv::Rect(0,0,-1,-1);
			}
		}
		
		// -- computing y-axis intersection -- //
		//intersection origin
		if ( firstRect.y <= secondRect.y ) {
			if ( secondRect.y < firstRect.y+firstRect.height) {
				resultRect.y = secondRect.y - firstRect.y;
				//intersection height
				if (resultRect.y + secondRect.height < firstRect.height) {
					resultRect.height = secondRect.height;
				} else {
					resultRect.height = firstRect.height - resultRect.y;
				}
			} else {
				return cv::Rect(0,0,-1,-1);
			}
		} else {
			if ( firstRect.y < secondRect.y+secondRect.height) {
				resultRect.y = 0; //crop interval start point inside firstRect 
				resultRect.height = secondRect.height - ( firstRect.y - secondRect.y );//crop interval height to match cropped startpoint
				//crop intersection height further to fit inside first rect
				if (firstRect.height < resultRect.y + resultRect.height) {
					resultRect.height = firstRect.height - resultRect.y;
				}  
			} else {
				return cv::Rect(0,0,-1,-1);
			}
		}
		
		return resultRect;
	}
}


#endif
